/*************************************************************************
Crytek Source File.
Copyright (C), Crytek Studios, 2001-2004.
-------------------------------------------------------------------------
$Id: TextureViewer.h  ,v 1.1 2008/08/28 09:28:02 PauloZaffari Exp wwwrun $
$DateTime$
Description:  This file implements the texture database item. Each item is
part of a texture database. The original database was created for the
texture browser control TextureViewer.
-------------------------------------------------------------------------
History:
- 28:08:2008   09:28 : Created by Paulo Zaffari

*************************************************************************/

#include "stdafx.h"
#include "TextureDatabaseItem.h"

#include "../Util/ImageUtil.h"

//////////////////////////////////////////////////////////////////////////
CTextureDatabaseItem::CTextureDatabaseItem():
m_strFilename(""),
m_strExtension(""),
m_strRelativePath(""),
m_strSurfaceTypeString(""),
m_boUsedInLevel(false),
m_boHasAlphaChannel(false),
m_boIsCubemap(false),
m_nTextureWidth(0),
m_nTextureHeight(0),
m_nMips(0),
m_nFileSize(0),
m_boVisible(true),
m_boBitmapIsChached(false),
m_boIsSelected(false),
m_boIsHover(false),
m_oDrawingRectangle(0,0,m_nTextureWidth,m_nTextureHeight)
{

}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
CTextureDatabaseItem::~CTextureDatabaseItem()
{
	if (m_boBitmapIsChached)
	{
		m_oCachedBitmap.DeleteObject();
	}	
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void		CTextureDatabaseItem::GetFilename(string& rstrFilename) const 
{ 
	rstrFilename=m_strFilename; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void		CTextureDatabaseItem::SetFilename(const string& val) 
{ 
	CString strSourceString(val);
	CString strDriveLetter;
	CString strDirectory;
	CString strFilename;
	CString strExtension;
	string	strResultingExtension;

	Path::SplitPath(strSourceString,strDriveLetter,strDirectory,strFilename,strExtension);

	m_strFilename = strFilename; 
	m_strFilename += strExtension;
	m_strExtension = strExtension;

	if (!strExtension.GetLength())
	{
		strResultingExtension=strExtension;
		SetExtension(strResultingExtension.substr(1));
	}	
	SetRelativePath((string)(strDriveLetter+strDirectory));
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void		CTextureDatabaseItem::GetExtension(string& rstrExtension) const 
{ 
	rstrExtension=m_strExtension; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void		CTextureDatabaseItem::SetExtension(const string& val) 
{ 
	m_strExtension = val; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void 		CTextureDatabaseItem::GetRelativePath(string& rstrRelativePath) const 
{ 
	rstrRelativePath=m_strRelativePath; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void		CTextureDatabaseItem::SetRelativePath(const string& val) 
{ 
	m_strRelativePath = val; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void		CTextureDatabaseItem::GetSurfaceType(string& rstrSurfaceTypeString) const 
{ 
	rstrSurfaceTypeString=m_strSurfaceTypeString; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void		CTextureDatabaseItem::SetSurfaceType(const string& val) 
{ 
	m_strSurfaceTypeString = val; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
bool		CTextureDatabaseItem::GetUsedInLevel() const 
{ 
	return m_boUsedInLevel; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void		CTextureDatabaseItem::SetUsedInLevel(bool val) 
{ 
	m_boUsedInLevel = val; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
bool CTextureDatabaseItem::GetHasAlphaChannelFlag() const
{
	return m_boHasAlphaChannel;
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void CTextureDatabaseItem::SetHasAlphaChannelFlag(bool val)
{
	m_boHasAlphaChannel=val;
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
bool CTextureDatabaseItem::GetIsCubemap() const
{
	return m_boIsCubemap;
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void CTextureDatabaseItem::SetIsCubeMap(bool boIsCubemap)
{
	m_boIsCubemap=boIsCubemap;
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
int			CTextureDatabaseItem::GetTextureWidth() const 
{ 
	return m_nTextureWidth; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void		CTextureDatabaseItem::SetTextureWidth(int val) 
{ 
	m_nTextureWidth = val; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
int			CTextureDatabaseItem::GetTextureHeight() const 
{
	return m_nTextureHeight; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void		CTextureDatabaseItem::SetTextureHeight(int val) 
{ 
	m_nTextureHeight = val; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
int			CTextureDatabaseItem::GetMips() const 
{ 
	return m_nMips; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void		CTextureDatabaseItem::SetMips(int val) 
{ 
	m_nMips = val; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
int			CTextureDatabaseItem::GetFileSize() const 
{ 
	return m_nFileSize; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void		CTextureDatabaseItem::SetFileSize(int val) 
{
	m_nFileSize = val; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
bool	CTextureDatabaseItem::GetVisibleFlag() const
{
	return m_boVisible;
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void	CTextureDatabaseItem::SetVisibleFlag(bool val)
{
	m_boVisible=val;
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
bool	CTextureDatabaseItem::GetSelectedFlag()
{ 
	return m_boIsSelected; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void	CTextureDatabaseItem::SetSelectedFlag(bool boIsSelected) 
{ 
	m_boIsSelected = boIsSelected; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
CRect& CTextureDatabaseItem::GetDrawingRectangle()
{ 
	return m_oDrawingRectangle; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
bool CTextureDatabaseItem::GetCachedFlag()
{
	return m_boBitmapIsChached;
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
CBitmap& CTextureDatabaseItem::GetBitmap()
{
	//if (!m_boBitmapIsChached)
	//{
	//	m_boBitmapIsChached=CacheBitmap();
	//}

	return m_oCachedBitmap;
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
bool CTextureDatabaseItem::CacheBitmap(bool boShowOnlyAlpha)
{
	if (m_boBitmapIsChached)
	{
		return true;
	}

	void *		pBitmapBits(NULL);
	CImage		oSourceImage;
	CImage		oTargetImage;

	oTargetImage.Allocate(m_oDrawingRectangle.Width(),m_oDrawingRectangle.Height());
	CImageUtil::LoadImage((m_strRelativePath+m_strFilename).c_str(),oSourceImage);

	if (!oSourceImage.IsValid())
	{
		m_boBitmapIsChached=false;
		return false;
	}

	// This way we will only need to do it once, instead of per frame basis (which in GDI is a problem).
	CImageUtil::ScaleToFit(oSourceImage,oTargetImage);
	oTargetImage.SwapRedAndBlue();
	pBitmapBits=oTargetImage.GetData();

	// We failed to cache this bitmap...
	if (!pBitmapBits)
	{
		m_boBitmapIsChached=false;
		return false;
	}

	if (boShowOnlyAlpha)
	{
		// Here we copy the alpha channel over the other channels making a 
		// grayscale bitmap with the alpha channel.
		GenerateAlphaMap(pBitmapBits,m_oDrawingRectangle.Width(),m_oDrawingRectangle.Height());
	}

	m_oCachedBitmap.CreateBitmap(m_oDrawingRectangle.Width(),m_oDrawingRectangle.Height(),1,32,	pBitmapBits);
	pBitmapBits=NULL;
	oSourceImage.Release();
	oTargetImage.Release();
	m_boBitmapIsChached=true;

	return m_boBitmapIsChached;
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
bool CTextureDatabaseItem::UnCacheBitmap()
{
	BOOL bnReturn(FALSE);
	if (!m_boBitmapIsChached)
	{
		return true;
	}

	bnReturn=m_oCachedBitmap.DeleteObject();
	if (bnReturn)
	{
		m_boBitmapIsChached=false;
		return true;
	}

	return false;
}
//////////////////////////////////////////////////////////////////////////
bool CTextureDatabaseItem::HitTest(int nX,int nY)
{
	CRect oTestRect(nX,nY,nX,nY);
	CRect oIntersection;

	if (
		((nX>=m_oDrawingRectangle.left)&&(nX<=m_oDrawingRectangle.right))
		&&
		((nY>=m_oDrawingRectangle.top)&&(nY<=m_oDrawingRectangle.bottom))
		)
	{
		return true;
	}
	else
	{
		return false;
	}
}
//////////////////////////////////////////////////////////////////////////
bool CTextureDatabaseItem::HitTest(const CRect& roTestRect)
{
	CRect oIntersection;
	return (oIntersection.IntersectRect(m_oDrawingRectangle,roTestRect)!=FALSE);
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void CTextureDatabaseItem::GenerateAlphaMap(void *pBitmapBits,int nWidth,int nHeight)
{
	unsigned char*	uchTexture((unsigned char*)pBitmapBits);
	unsigned char   uchAlphaByte(0);
	int							nCurrentX(0),nCurrentY(0);
	int             nCurrentOfsset(0);

	if (!uchTexture)
	{
		return;
	}

	for (nCurrentX=0;nCurrentX<nWidth;++nCurrentX)
	{
		for (nCurrentY=0;nCurrentY<nHeight;++nCurrentY)
		{
			// As we know our format is 32 bit, we also know it is 4 times unsinged char size.
			// As the format is RGBA, the last byte is the alpha byte, and so is the one we 
			// have to propagate to all other channels.
			nCurrentOfsset=nCurrentX*4+nCurrentY*nWidth*4;
			uchAlphaByte=uchTexture[nCurrentOfsset+3];
			uchTexture[nCurrentOfsset+0]=uchAlphaByte;
			uchTexture[nCurrentOfsset+1]=uchAlphaByte;
			uchTexture[nCurrentOfsset+2]=uchAlphaByte;
		}
	}
}
//////////////////////////////////////////////////////////////////////////
bool	CTextureDatabaseItem::GetHoverFlag()
{ 
	return m_boIsHover; 
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void	CTextureDatabaseItem::SetHoverFlag(bool boIsHover) 
{ 
	m_boIsHover = boIsHover; 
}
//////////////////////////////////////////////////////////////////////////
